package com.larly.service.impl;

import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.larly.exception.ErrorCode;
import com.larly.exception.ThrowUtils;
import com.larly.model.domain.Notification;
import com.larly.model.domain.PrivateMessage;
import com.larly.model.domain.User;
import com.larly.model.dto.notification.NotificationCreateRequest;
import com.larly.model.dto.notification.NotificationSelectRequest;
import com.larly.model.enums.notification.NotificationTypeEnum;
import com.larly.model.vo.NotificationVO;
import com.larly.service.NotificationService;
import com.larly.mapper.NotificationMapper;
import com.larly.service.UserService;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author 许颢达
* @description 针对表【notification(消息通知表)】的数据库操作Service实现
* @createDate 2025-09-02 12:31:02
*/
@Service
public class NotificationServiceImpl extends ServiceImpl<NotificationMapper, Notification>
    implements NotificationService{

    @Resource
    @Lazy
    private UserService userService;

    /**
     * 创建消息通知
     * @param notificationCreateRequest
     */
    @Override
    public boolean createNotification(NotificationCreateRequest notificationCreateRequest) {
        // 1、校验：不能给自己发送通知
        Integer receiverId = notificationCreateRequest.getReceiverId();
        Integer senderId = notificationCreateRequest.getSenderId();
        ThrowUtils.throwIf(receiverId.equals(senderId), ErrorCode.PARAM_ERROR, "不能给自己发送通知");

        // 2、创建消息通知
        Notification notification = new Notification();
        notification.setUserId(notificationCreateRequest.getReceiverId());
        notification.setSenderId(notificationCreateRequest.getSenderId());
        notification.setType(notificationCreateRequest.getType());
        notification.setContent(notificationCreateRequest.getContent());
        notification.setRelatedId(notificationCreateRequest.getRelatedId());
        // 默认未读
        notification.setIsRead(0);
        return this.save(notification);
    }

    /**
     * 构建查询条件
     * @param notificationSelectRequest
     * @return
     */
    @Override
    public QueryWrapper<Notification> buildQueryWrapper(NotificationSelectRequest notificationSelectRequest) {
        QueryWrapper<Notification> queryWrapper = new QueryWrapper<>();
        if (notificationSelectRequest == null){
            return queryWrapper;
        }
        Integer id = notificationSelectRequest.getId();
        Integer userId = notificationSelectRequest.getUserId();
        Integer type = notificationSelectRequest.getType();
        Integer relatedId = notificationSelectRequest.getRelatedId();
        Integer isRead = notificationSelectRequest.getIsRead();

        queryWrapper.eq(ObjUtil.isNotNull(id), "id", id);
        queryWrapper.eq(ObjUtil.isNotNull(userId), "user_id", userId);
        queryWrapper.eq(ObjUtil.isNotNull(type), "type", type);
        queryWrapper.eq(ObjUtil.isNotNull(relatedId), "related_id", relatedId);
        queryWrapper.eq(ObjUtil.isNotNull(isRead), "is_read", isRead);

        return queryWrapper;

    }

    /**
     * 查询用户消息通知
     * @param queryWrapper
     * @param notificationSelectRequest
     * @return
     */
    @Override
    public List<NotificationVO> queryUserNotification(QueryWrapper<Notification> queryWrapper, NotificationSelectRequest notificationSelectRequest) {
        Integer pageNum = notificationSelectRequest.getPageNum();
        Integer pageSize = notificationSelectRequest.getPageSize();
        Page<Notification> page = new Page<>(pageNum, pageSize);
        Page<Notification> notificationPage = this.page(page, queryWrapper);

        // 转换为VO
        return notificationPage.convert(notification -> {
            User sender = userService.getById(notification.getSenderId());
            String nickname = sender != null ? sender.getNickname() : "匿名用户";
            String avatar = sender != null ? sender.getAvatar() : "";
            return NotificationVO.fromEntity(notification, nickname, avatar);
        }).getRecords();


    }


    /**
     * 批量标记已读
     * @param ids
     * @return
     */
    @Override
    public boolean readBatchNotification(List<Integer> ids ,Integer userId) {
        ThrowUtils.throwIf(ids == null || ids.isEmpty(), ErrorCode.PARAM_ERROR, "参数错误");
        List<Notification> collect = ids.stream().map(id -> {
            Notification notification = new Notification();
            notification.setId(id);
            notification.setIsRead(1);
            notification.setUserId(userId);
            return notification;
        }).collect(Collectors.toList());
        boolean result = updateBatchById(collect);
        ThrowUtils.throwIf(!result, ErrorCode.SYSTEM_ERROR, "批量标记已读失败");
        return true;
    }

    /**
     * 获取未读消息数量
     * @param request
     * @return
     */
    @Override
    public long getUnreadCount(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        ThrowUtils.throwIf(loginUser == null, ErrorCode.NOT_LOGIN, "用户未登录");
        Integer userId = loginUser.getId();
        QueryWrapper<Notification> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        queryWrapper.eq("is_read", 0);
        return this.count(queryWrapper);
    }

    // ------------------------------业务逻辑---------------------------------
    /**
     * 触发笔记点赞通知
     * @param noteId 笔记 ID
     * @param noteTitle 笔记标题
     * @param likerId 点赞者 ID
     * @param noteAuthorId 笔记作者 ID
     */
    @Override
    public void triggerNoteLikeNotify(Integer noteId, String noteTitle, Integer likerId, Integer noteAuthorId) {
        // 查询用户
        User liker = userService.getById(likerId);
        NotificationCreateRequest notificationCreateRequest = new NotificationCreateRequest();
        notificationCreateRequest.setReceiverId(noteAuthorId);
        notificationCreateRequest.setSenderId(likerId);
        notificationCreateRequest.setType(NotificationTypeEnum.LIKE.getCode());
        notificationCreateRequest.setRelatedId(noteId);
        String content = String.format("用户 %s 赞了你的笔记 %s", liker.getNickname(), noteTitle);
        notificationCreateRequest.setContent(content);

        createNotification(notificationCreateRequest);

    }


    /**
     * 触发笔记评论通知
     * @param noteId 笔记 ID
     * @param noteTitle 笔记标题
     * @param commentContent 评论内容
     * @param commenterId 评论者 ID
     * @param noteAuthorId 笔记作者 ID
     */
    @Override
    public void triggerNoteCommentNotify(Integer noteId, String noteTitle, String commentContent, Integer commenterId, Integer noteAuthorId) {
        // 获取用户
        User commenter = userService.getById(commenterId);
        NotificationCreateRequest notificationCreateRequest = new NotificationCreateRequest();
        notificationCreateRequest.setReceiverId(noteAuthorId);
        notificationCreateRequest.setSenderId(commenterId);
        notificationCreateRequest.setType(NotificationTypeEnum.COMMENT.getCode());
        notificationCreateRequest.setRelatedId(noteId);
        String content = String.format("用户 %s 评论了你的笔记 %s: %s", commenter.getNickname(), noteTitle, commentContent);
        notificationCreateRequest.setContent(content);
        createNotification(notificationCreateRequest);
    }

    /**
     * 触发评论点赞通知
     * @param commentId 评论 ID
     * @param commentContent 评论内容
     * @param likerId 点赞者 ID
     * @param commentAuthorId 评论作者 ID
     */
    @Override
    public void triggerCommentLikeNotify(Integer commentId, String commentContent, Integer likerId, Integer commentAuthorId) {
        // 获取用户
        User liker = userService.getById(likerId);
        NotificationCreateRequest notificationCreateRequest = new NotificationCreateRequest();
        notificationCreateRequest.setReceiverId(commentAuthorId);
        notificationCreateRequest.setSenderId(likerId);
        notificationCreateRequest.setType(NotificationTypeEnum.LIKE.getCode());
        notificationCreateRequest.setRelatedId(commentId);
        String content = String.format("用户 %s 赞了你的评论: %s", liker.getNickname(), commentContent);
        notificationCreateRequest.setContent(content);
        createNotification(notificationCreateRequest);
    }

    /**
     * 触发评论回复通知
     * @param parentInteractionId 父级互动 ID
     * @param parentContent 父级互动内容
     * @param replierId 回复者 ID
     * @param interactionAuthorId 互动作者 ID
     */
    @Override
    public void triggerCommentReplyNotify(Integer parentInteractionId, String parentContent, Integer replierId, Integer interactionAuthorId) {
        // 获取用户
        User replier = userService.getById(replierId);
        NotificationCreateRequest notificationCreateRequest = new NotificationCreateRequest();
        notificationCreateRequest.setReceiverId(interactionAuthorId);
        notificationCreateRequest.setSenderId(replierId);
        notificationCreateRequest.setType(NotificationTypeEnum.COMMENT.getCode());
        notificationCreateRequest.setRelatedId(parentInteractionId);
        String content = String.format("用户 %s 回复了你的评论: %s", replier.getNickname(), parentContent);
        notificationCreateRequest.setContent(content);
        createNotification(notificationCreateRequest);
    }

    /**
     * 触发关注通知
     * @param followerId 关注者 ID
     * @param followedId 被关注者 ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void triggerFollowNotify(Integer followerId, Integer followedId) {
        // 获取用户
        User follower = userService.getById(followerId);
        NotificationCreateRequest notificationCreateRequest = new NotificationCreateRequest();
        notificationCreateRequest.setReceiverId(followedId);
        notificationCreateRequest.setSenderId(followerId);
        notificationCreateRequest.setType(NotificationTypeEnum.FOLLOW.getCode());
        notificationCreateRequest.setRelatedId(followerId);
        String content = String.format("用户 %s 关注了你", follower.getNickname());
        notificationCreateRequest.setContent(content);
        createNotification(notificationCreateRequest);
    }

    /**
     * 触发私信通知
     * @param senderId 发送者 ID
     * @param receiverId 接收者 ID
     * @param content 私信内容
     */
    @Override
    public void triggerPrivateMessageNotify(Integer senderId, Integer receiverId, String content) {
        NotificationCreateRequest notificationCreateRequest = new NotificationCreateRequest();
        notificationCreateRequest.setReceiverId(receiverId);
        notificationCreateRequest.setSenderId(senderId);
        notificationCreateRequest.setType(NotificationTypeEnum.PRIVATE_MESSAGE.getCode());
        notificationCreateRequest.setRelatedId(senderId);
        String msg = String.format("用户 %s 给你发来私信: %s", senderId, content);
        notificationCreateRequest.setContent(msg);
        createNotification(notificationCreateRequest);
    }

}




